package cn.wen.yaling.xo.service.impl;

import cn.wen.yaling.commons.constant.Constants;
import cn.wen.yaling.commons.constant.RedisConstants;
import cn.wen.yaling.commons.service.RedisService;
import cn.wen.yaling.commons.utils.*;
import cn.wen.yaling.commons.vo.ConfigVO;
import cn.wen.yaling.commons.vo.WebConfigVO;
import cn.wen.yaling.xo.dao.WebVisitDao;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.TimeUnit;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import cn.wen.yaling.xo.dao.WebConfigDao;
import cn.wen.yaling.commons.entity.WebConfigEntity;
import cn.wen.yaling.xo.service.WebConfigService;


@Service("webConfigService")
@Slf4j
public class WebConfigServiceImpl extends ServiceImpl<WebConfigDao, WebConfigEntity> implements WebConfigService {

    @Autowired
    private WebConfigDao webConfigDao;

    @Autowired
    private RedisService redisService;

    @Autowired
    private WebVisitDao webVisitDao;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<WebConfigEntity> page = this.page(
                new Query<WebConfigEntity>().getPage(params),
                new QueryWrapper<WebConfigEntity>()
        );

        return new PageUtils(page);
    }

    @Override
    public ConfigVO getConfigInfoIsActive() {
        ConfigVO target = new ConfigVO(); ;
        QueryWrapper<WebConfigEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("status", 1);
        WebConfigEntity configEntity = webConfigDao.selectOne(queryWrapper);
        BeanUtils.copyProperties(configEntity, target);
        String[] split = configEntity.getShowList().split(",");
        String[] logins = configEntity.getLoginTypeList().split(",");
        int[] ints = Arrays.stream(split).mapToInt(Integer::parseInt).toArray();
        int[] loginList = Arrays.stream(logins).mapToInt(Integer::parseInt).toArray();
        target.setShowList(ints);
        target.setLoginTypeList(loginList);
        return target;
    }

    @Override
    public void addConfigViews() {
        // 获取用户访问量
        QueryWrapper<WebConfigEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("status", 1);
        WebConfigEntity configEntity = webConfigDao.selectOne(queryWrapper);
        // 然后更新
        WebConfigEntity configEntity1 = new WebConfigEntity();
        configEntity1.setConfigId(configEntity.getConfigId());
        configEntity1.setConfigViews(configEntity.getConfigViews() + 1);
        webConfigDao.updateById(configEntity1);
    }

    @Override
    public Map<String, Object> getWebVisitByWeek() {
        // 从Redis中获取一周访问量
        String weekVisitJson = (String) redisService.get("DASHBOARD" + Constants.SYMBOL_COLON + "WEEK_VISIT");
        if (StringUtils.isNotEmpty(weekVisitJson)) {
            Map<String, Object> weekVisitMap = JsonUtils.jsonToMap(weekVisitJson);
            return weekVisitMap;
        }

        // 获取到今天结束的时间
        String todayEndTime = DateUtils.getToDayEndTime();
        //获取最近七天的日期
        Date sevenDaysDate = DateUtils.getDate(todayEndTime, -6);
        String sevenDays = DateUtils.getOneDayStartTime(sevenDaysDate);
        // 获取最近七天的数组列表
        List<String> sevenDaysList = DateUtils.getDaysByN(7, "yyyy-MM-dd");
        // 获得最近七天的访问量
        List<Map<String, Object>> pvMap = webVisitDao.getPVByWeek(sevenDays, todayEndTime);
        // 获得最近七天的独立用户
        List<Map<String, Object>> uvMap = webVisitDao.getUVByWeek(sevenDays, todayEndTime);

        Map<String, Object> countPVMap = new HashMap<>();
        Map<String, Object> countUVMap = new HashMap<>();

        for (Map<String, Object> item : pvMap) {
            countPVMap.put(item.get("DATE").toString(), item.get("COUNT"));
        }
        for (Map<String, Object> item : uvMap) {
            countUVMap.put(item.get("DATE").toString(), item.get("COUNT"));
        }
        // 访问量数组
        List<Integer> pvList = new ArrayList<>();
        // 独立用户数组
        List<Integer> uvList = new ArrayList<>();

        for (String day : sevenDaysList) {
            if (countPVMap.get(day) != null) {
                Number pvNumber = (Number) countPVMap.get(day);
                Number uvNumber = (Number) countUVMap.get(day);
                pvList.add(pvNumber.intValue());
                uvList.add(uvNumber.intValue());
            } else {
                pvList.add(0);
                uvList.add(0);
            }
        }
        Map<String, Object> resultMap = new HashMap<>(Constants.NUM_THREE);
        // 不含年份的数组格式
        List<String> resultSevenDaysList = DateUtils.getDaysByN(7, "MM-dd");
        resultMap.put("date", resultSevenDaysList);
        resultMap.put("pv", pvList);
        resultMap.put("uv", uvList);

        // TODO 可能会存在短期的数据不一致的问题，即零点时不能准时更新，而是要在0:10才会重新刷新纪录。 后期考虑加入定时器处理这个问题
        // 将一周访问量存入Redis中【过期时间10分钟】
        redisService.setEx("DASHBOARD" + Constants.SYMBOL_COLON + "WEEK_VISIT", JsonUtils.objectToJson(resultMap), 10, TimeUnit.MINUTES);
        return resultMap;
    }

    @Override
    public Long getWebVisitCount() {
        // 获取今日开始和结束时间
        String startTime = DateUtils.getToDayStartTime();
        String endTime = DateUtils.getToDayEndTime();
        return webVisitDao.getIpCount(startTime, endTime);
    }

    @Override
    public ResultEntity editWebConfig(WebConfigVO webConfigVO) {
        WebConfigEntity target = new WebConfigEntity();
        BeanUtils.copyProperties(webConfigVO, target);
        QueryWrapper<WebConfigEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("status", 1);
        boolean res = webConfigDao.update(target, queryWrapper) > 0;
        if (res) return ResultEntity.ok();
        return ResultEntity.error();
    }

}